import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

// 游标卡尺组件
class InfiniteCaliper extends LeafRenderObjectWidget {
  // 主刻度间隔（毫米）
  final double mainScaleInterval;
  // 主刻度之间的细分刻度数量
  final int subDivisions;
  // 组件高度
  final double height;
  // 可视宽度
  final double visibleWidth;
  // 初始值
  final double initialValue;
  // 数值变化回调
  final ValueChanged<double>? onValueChanged;

  const InfiniteCaliper({
    super.key,
    this.mainScaleInterval = 10.0, // 10mm一个主刻度
    this.subDivisions = 10, // 每个主刻度分10份
    this.height = 120.0,
    this.visibleWidth = 300.0,
    this.initialValue = 0.0,
    this.onValueChanged,
  }) : assert(subDivisions > 0);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderInfiniteCaliper(
      mainScaleInterval: mainScaleInterval,
      subDivisions: subDivisions,
      height: height,
      visibleWidth: visibleWidth,
      initialValue: initialValue,
      onValueChanged: onValueChanged,
    );
  }

  @override
  void updateRenderObject(BuildContext context, RenderInfiniteCaliper renderObject) {
    renderObject
      ..mainScaleInterval = mainScaleInterval
      ..subDivisions = subDivisions
      ..height = height
      ..visibleWidth = visibleWidth
      ..onValueChanged = onValueChanged;
  }
}

// 游标卡尺渲染对象
class RenderInfiniteCaliper extends RenderBox {
  double _mainScaleInterval;
  int _subDivisions;
  double _height;
  double _visibleWidth;
  ValueChanged<double>? _onValueChanged;
  
  // 滑动偏移量（与当前值相关联）
  double _offsetX = 0.0;
  // 单个细分刻度的像素宽度
  double get _subScalePixelWidth => _mainScalePixelWidth / _subDivisions;
  // 主刻度的像素宽度
  double get _mainScalePixelWidth => 40.0; // 每个主刻度占40像素
  // 总刻度周期宽度（一个周期的像素宽度）
  double get _cycleWidth => _mainScalePixelWidth * 5; // 5个主刻度为一个周期
  
  // 触摸状态
  double? _startTouchX;
  double? _startOffsetX;
  bool _isDragging = false;

  // 当前测量值
  double get currentValue => (_offsetX / _mainScalePixelWidth) * _mainScaleInterval;

  RenderInfiniteCaliper({
    required double mainScaleInterval,
    required int subDivisions,
    required double height,
    required double visibleWidth,
    required double initialValue,
    ValueChanged<double>? onValueChanged,
  })  : _mainScaleInterval = mainScaleInterval,
        _subDivisions = subDivisions,
        _height = height,
        _visibleWidth = visibleWidth,
        _onValueChanged = onValueChanged {
    // 根据初始值计算偏移量
    _offsetX = (initialValue / mainScaleInterval) * _mainScalePixelWidth;
  }

  // 设置属性的setter
  set mainScaleInterval(double value) {
    if (_mainScaleInterval != value) {
      _mainScaleInterval = value;
      markNeedsPaint();
    }
  }

  set subDivisions(int value) {
    if (_subDivisions != value && value > 0) {
      _subDivisions = value;
      markNeedsPaint();
    }
  }

  set height(double value) {
    if (_height != value) {
      _height = value;
      markNeedsLayout();
    }
  }

  set visibleWidth(double value) {
    if (_visibleWidth != value) {
      _visibleWidth = value;
      markNeedsLayout();
    }
  }

  set onValueChanged(ValueChanged<double>? value) {
    _onValueChanged = value;
  }

  // 标准化偏移量，实现无限循环
  void _normalizeOffset() {
    _offsetX = _offsetX % _cycleWidth;
    if (_offsetX < 0) _offsetX += _cycleWidth;
  }

  // 吸附到最近的细分刻度
  void _snapToGrid() {
    final nearestSubDivision = (_offsetX / _subScalePixelWidth).round();
    _offsetX = nearestSubDivision * _subScalePixelWidth;
    _normalizeOffset();
    markNeedsPaint();
    _onValueChanged?.call(currentValue);
  }

  // 处理触摸事件
  @override
  bool hitTestSelf(Offset position) => true;

  @override
  void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
    super.handleEvent(event, entry);

    if (event is PointerDownEvent) {
      _startTouchX = event.localPosition.dx;
      _startOffsetX = _offsetX;
      _isDragging = true;
    } else if (event is PointerMoveEvent && _startTouchX != null && _startOffsetX != null) {
      // 计算滑动偏移
      final deltaX = event.localPosition.dx - _startTouchX!;
      _offsetX = _startOffsetX! - deltaX; // 反向滑动
      
      _normalizeOffset();
      markNeedsPaint();
      
      // 实时通知值变化（可选）
      if (_isDragging) {
        _onValueChanged?.call(currentValue);
      }
    } else if ((event is PointerUpEvent || event is PointerCancelEvent) && _isDragging) {
      _isDragging = false;
      _startTouchX = null;
      _startOffsetX = null;
      
      // 滑动结束后吸附到最近的刻度
      _snapToGrid();
    }
  }

  // 布局逻辑
  @override
  void performLayout() {
    size = Size(_visibleWidth, _height);
  }

  // 绘制刻度线
  void _paintScale(Canvas canvas, Offset offset) {
    final paint = Paint()
      ..color = Colors.black87
      ..strokeWidth = 1.0;

    // 主刻度高度和次刻度高度
    const mainScaleHeight = 30.0;
    const subScaleHeight = 15.0;

    // 绘制多个周期的刻度，实现无限滑动效果
    for (int cycle = -2; cycle <= 2; cycle++) {
      final cycleOffset = cycle * _cycleWidth;
      
      // 绘制主刻度
      for (int i = 0; i < 5; i++) { // 每个周期5个主刻度
        final x = cycleOffset + i * _mainScalePixelWidth - _offsetX;
        
        // 只绘制可视范围内的刻度
        if (x < -5 || x > _visibleWidth + 5) continue;
        
        // 主刻度线
        canvas.drawLine(
          Offset(x, offset.dy + 20),
          Offset(x, offset.dy + 20 + mainScaleHeight),
          paint,
        );
        
        // 主刻度数值
        final value = ((cycle * 5 + i) * _mainScaleInterval + 
                      (currentValue % _mainScaleInterval).roundToDouble())
                      .toStringAsFixed(1);
        
        final textPainter = TextPainter(
          text: TextSpan(
            text: value,
            style: const TextStyle(color: Colors.black87, fontSize: 12),
          ),
          textDirection: TextDirection.ltr,
        );
        textPainter.layout();
        textPainter.paint(
          canvas,
          Offset(
            x - textPainter.width / 2,
            offset.dy + 20 + mainScaleHeight + 5,
          ),
        );
        
        // 绘制细分刻度
        for (int j = 1; j < _subDivisions; j++) {
          final subX = x + j * _subScalePixelWidth;
          canvas.drawLine(
            Offset(subX, offset.dy + 20 + (mainScaleHeight - subScaleHeight)),
            Offset(subX, offset.dy + 20 + mainScaleHeight),
            paint,
          );
        }
      }
    }
  }

  // 绘制游标
  void _paintCursor(Canvas canvas, Offset offset) {
    const cursorWidth = 3.0;
    const cursorHeight = 60.0;
    
    // 游标位置在组件中间
    final cursorX = offset.dx + _visibleWidth / 2;
    
    // 绘制游标竖线
    canvas.drawLine(
      Offset(cursorX, offset.dy + 20),
      Offset(cursorX, offset.dy + 20 + cursorHeight),
      Paint()
        ..color = Colors.red
        ..strokeWidth = cursorWidth
        ..strokeCap = StrokeCap.round,
    );
    
    // 绘制游标上下三角形
    final path = Path();
    // 上方三角形
    path.moveTo(cursorX - 8, offset.dy + 20);
    path.lineTo(cursorX + 8, offset.dy + 20);
    path.lineTo(cursorX, offset.dy + 10);
    path.close();
    
    // 下方三角形
    path.moveTo(cursorX - 8, offset.dy + 20 + cursorHeight);
    path.lineTo(cursorX + 8, offset.dy + 20 + cursorHeight);
    path.lineTo(cursorX, offset.dy + 30 + cursorHeight);
    path.close();
    
    canvas.drawPath(path, Paint()..color = Colors.red);
  }

  // 绘制当前数值
  void _paintValueDisplay(Canvas canvas, Offset offset) {
    final displayValue = currentValue.toStringAsFixed(1);
    
    final textPainter = TextPainter(
      text: TextSpan(
        text: '$displayValue mm',
        style: const TextStyle(
          color: Colors.black87,
          fontSize: 18,
          fontWeight: FontWeight.bold,
        ),
      ),
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();
    textPainter.paint(
      canvas,
      Offset(
        offset.dx + (_visibleWidth - textPainter.width) / 2,
        offset.dy + _height - 30,
      ),
    );
  }

  // 绘制背景和边框
  void _paintBackground(Canvas canvas, Offset offset) {
    // 绘制背景
    canvas.drawRect(
      offset & size,
      Paint()..color = Colors.grey[100]!,
    );
    
    // 绘制边框
    canvas.drawRect(
      offset & size,
      Paint()
        ..color = Colors.grey[300]!
        ..style = PaintingStyle.stroke
        ..strokeWidth = 1.0,
    );
  }

  // 总绘制逻辑
  @override
  void paint(PaintingContext context, Offset offset) {
    final canvas = context.canvas;
    
    canvas.save();
    
    // 1. 绘制背景
    _paintBackground(canvas, offset);
    
    // 2. 绘制刻度
    _paintScale(canvas, offset);
    
    // 3. 绘制游标
    _paintCursor(canvas, offset);
    
    // 4. 绘制当前数值
    _paintValueDisplay(canvas, offset);
    
    canvas.restore();
  }

  @override
  bool get isRepaintBoundary => true;
}

// 使用示例
class CaliperDemo extends StatelessWidget {
  const CaliperDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('无限滑动游标卡尺')),
      body: const Padding(
        padding: EdgeInsets.all(20.0),
        child: Column(
          children: [
            Text('左右滑动标尺测量数值：'),
            SizedBox(height: 20),
            InfiniteCaliper(
              visibleWidth: 300,
              height: 150,
              initialValue: 0,
            ),
            SizedBox(height: 20),
            Text('游标指向的位置即为测量值，单位：毫米(mm)'),
          ],
        ),
      ),
    );
  }
}
